/*
 * Created on 2007
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.XSQS.storage.thread;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
import com.XSQS.storage.helper.FileName;
import com.XSQS.storage.manager.DataFileManager;
import com.XSQS.storage.manager.FileManager;
import com.XSQS.storage.manager.FreePageManager.InnerManager;
import com.XSQS.storage.util.DataPage;
import com.XSQS.storage.util.DocInfoPage;
import com.XSQS.storage.util.Page;
import com.XSQS.storage.util.StringPage;

/**
 * @author Jofee.Chan
 */
public class FPThread implements Runnable{
    private DataFileManager dfm;
    private FileManager fm;
    private InnerManager im;
    private RandomAccessFile raf;
    private int type, pageSize;
    private int lpno, num;
    private int[] fp;
    private boolean isSet;
    private Map fileMap;
    private boolean shutdownRequested;
    /** Creates a new instance of FPThread */
    public FPThread(InnerManager im, int type){
        dfm = DataFileManager.getInstance();
        fm = FileManager.getInstance();
        this.im =im;
        this.type = type;
        pageSize = getPageSize(type);
        fileMap = new HashMap();
        isSet = false;
        shutdownRequested = false;
    }
    
    public synchronized void setParam(int lpno, int num){
        if(!isSet){
            this .lpno = lpno;
            this.num = num;
            fp = new int[num];
            isSet = true;
            notifyAll();
        }
    }
    
    public synchronized int[] getFreePage(){
        return fp;
    }
    
    public int getType(){
        return this.type;
    }
    
    public void run() {
        while(!shutdownRequested){
            if(isSet){
                int i = 0;
                short status;
                int nextPage = lpno;
                try {
                    for(i = 0; i< this.num; i++){
                        raf = openFile(nextPage);
                        if(raf == null){
                            break;    //
                        } else if(raf.length() >= (nextPage + 1) * this.pageSize){
                            raf.seek(nextPage * this.pageSize);
                            status = raf.readShort();
                            nextPage = raf.readInt();
                            if(status == 0){
                                if(nextPage == 0){
                                    break; //
                                }
                                fp[i] = nextPage;
                            }else{
                                System.err.println("Fatal Error! [FPThread] Found Used Page int FreePage Link!");
                            }
                        }else{
                            break;  //
                        }
                    }
                    int startPos = i, startPage = 0;;
                    if(i == 0){
                        //startPos = 0;
                        startPage = lpno;
                    }else{
                        startPage = fp[i-1];
                    }
                    for(int j = startPos; j < this.num; j++){
                        fp[j] = ++startPage;//update from "startPage++" to "++startPage" 09-5-7
                    }
                    isSet = false;
                    im.fillFreePage(fp);                                  
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }else{
                synchronized(this){
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                        //ex.printStackTrace();
                        System.out.println("FTPThread[" + type + "] Interrupted!");
                    }
                }
            }
        }
        System.out.println("FTPThread[" + type + "] ended!");
    }
    
    public void shutdown(){
        this.shutdownRequested = true;
    }
    
    private RandomAccessFile openFile(int lpno){
        String fileName = getFileName(this.type, lpno);
        RandomAccessFile raf = null;
        if(fileMap.get(fileName) == null){
            try {
                File f = new File(fileName);
                if(f.exists()){
                    raf = new RandomAccessFile(f, "r");
                    fileMap.put(fileName, raf);
                }
            } catch (FileNotFoundException ex) {
                ex.printStackTrace();
                return null;
            }
        }else{
            raf = (RandomAccessFile)fileMap.get(fileName);
        }
        return raf;
    }
    
    private String getFileName(int type, int lpno){
        switch(type){
            case Page.DOCINFOPAGE:
                return FileName.getDocInfoFile(lpno);
            case Page.DATAPAGE:
                return FileName.getDataFile(lpno);
            case Page.STRINGPAGE:
                return FileName.getStringFile(lpno);
            default:
                return null;
        }
    }
    
    private int getPageSize(int type){
        int pSize = 0;
        switch(type){
            case Page.DOCINFOPAGE:
                pSize = DocInfoPage.PAGE_SIZE;
                break;
            case Page.DATAPAGE:
                pSize = DataPage.PAGE_SIZE;
                break;
            case Page.STRINGPAGE:
                pSize = StringPage.PAGE_SIZE;
                break;
            default:
                System.err.println("Error Page type: " + type);
                //pSize = 0;
                break;
        }
        return pSize;
    }
    
}
